﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BackOfficerControl.cs" company="">
//   
// </copyright>
// <summary>
//   The trader form.
// </summary>
// --------------------------------------------------------------------------------------------------------------------


using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Systemathics.FrameWork;
using Systemathics.UserControls.Properties;


namespace Systemathics.UserControls
{
    [ToolboxBitmap(typeof(BackOfficeControl), "UserControlsIcon.bmp")]
    public sealed partial class BackOfficeControl : UserControl
    {
        private ToolStripControlHost dateTimePickerHost;
        private readonly SystemathicsEntities db;
        private readonly Dictionary<Guid, List<Instrument>> Instruments;
        private readonly Dictionary<Guid, List<Order>> InventoryOrders, TradedOrders;
        private Dictionary<Guid, String> StrategyDetails;
        private DateTime SelectedDate;

        public DataService DataService { get; set; }
        public OrderService OrderService { get; set; }

        public BackOfficeControl()
        {
            InitializeComponent();

            Dock = DockStyle.Fill;
            DoubleBuffered = true;
            SelectedDate = DateTime.Today;
            Instruments = new Dictionary<Guid, List<Instrument>>();
            InventoryOrders = new Dictionary<Guid, List<Order>>();
            TradedOrders = new Dictionary<Guid, List<Order>>();
            StrategyDetails = new Dictionary<Guid, String>();
            Thread.CurrentThread.CurrentCulture = GlobalVariables.SystemathicsCulture();
            db = new SystemathicsEntities(GlobalVariables.EntitiesConnectionString());
            db.AcceptAllChanges();
        }

        public void MenuItemClick(object sender, EventArgs e)
        {
            notifyIcon1.Dispose();
            if (ParentForm != null) ParentForm.Close();
        }
        private void BorderItemClick(object sender, EventArgs e)
        {
            if (ParentForm != null)
                if (ParentForm.FormBorderStyle == FormBorderStyle.Sizable)
                {
                    ParentForm.FormBorderStyle = FormBorderStyle.None;
                    ParentForm.ControlBox = false;
                }
                else
                {
                    ParentForm.FormBorderStyle = FormBorderStyle.Sizable;
                    ParentForm.ControlBox = true;
                }
        }
        private void NotiftyIconClick(object sender, EventArgs e)
        {
            if (ParentForm != null)
            {
                if (ParentForm.WindowState == FormWindowState.Minimized)
                {
                    ParentForm.Show();
                    ParentForm.WindowState = FormWindowState.Normal;
                }

                ParentForm.Activate();
            }
        }
        private void ParentFormResize(object sender, EventArgs e)
        {
            if (ParentForm != null)
                if (ParentForm.WindowState == FormWindowState.Minimized)
                    ParentForm.Hide();
        }
        private void ParentFormFormClosing(object sender, FormClosingEventArgs e)
        {
            notifyIcon1.Dispose();
        }
        private void HideShowtoolStripButton_Click(object sender, System.EventArgs e)
        {
            var bt = sender as ToolStripButton;
            if (bt.CheckState == CheckState.Checked)
                splitContainer1.Panel2Collapsed = true;
            else if (bt.CheckState == CheckState.Unchecked)
                splitContainer1.Panel2Collapsed = false;
        }
        private void BackOffice_Load(object sender, EventArgs eqs)
        {
            Dock = DockStyle.Fill;
            if (ParentForm != null)
            {
                ParentForm.Name = "Back Office";
                ParentForm.Icon = Icon.FromHandle(Resources.MSN_Explorer.GetHicon());
                ParentForm.ShowIcon = true;
                ParentForm.SizeGripStyle = SizeGripStyle.Hide;
                ParentForm.MaximizeBox = true;
                ParentForm.MinimizeBox = true;
                ParentForm.StartPosition = FormStartPosition.CenterScreen;
                ParentForm.FormBorderStyle = FormBorderStyle.Sizable;
                ParentForm.ControlBox = true;
                ParentForm.Opacity = 0.9;

                ParentForm.FormClosing += ParentFormFormClosing;
                ParentForm.Resize += ParentFormResize;
            }
            var exitItem = new MenuItem { Index = 0, Text = "E&xit Instruments Container" };
            var borderItem = new MenuItem { Index = 0, Text = "H&ide/Show Borders" };
            borderItem.Click += BorderItemClick;
            exitItem.Click += MenuItemClick;

            var menu = new ContextMenu();
            menu.MenuItems.Add(borderItem);
            menu.MenuItems.Add(exitItem);

            notifyIcon1.Icon = Icon.FromHandle(Resources.MSN_Explorer.GetHbitmap());
            notifyIcon1.ContextMenu = menu;
            notifyIcon1.Text = "Back Office";
            notifyIcon1.Visible = true;
            notifyIcon1.Click += NotiftyIconClick;

            notifyIcon1.BalloonTipText = "Back Office Loaded";
            notifyIcon1.ShowBalloonTip(1000);

            dateTimePickerHost = new ToolStripControlHost(new DateTimePicker())
                                     {
                                         Font = new Font("Arial", 9.0F, FontStyle.Italic),
                                         Width = 100,
                                         DisplayStyle = ToolStripItemDisplayStyle.Text,
                                         Text = SelectedDate.ToShortDateString()
                                     };
            ((DateTimePicker)dateTimePickerHost.Control).Format = DateTimePickerFormat.Short;
            StrategyToolStrip.Items.Add(dateTimePickerHost);
            dateTimePickerHost.Validated += DateTimePickerHostValidated;

            foreach(Guid g in db.DBStrategies.Select(i => i.ID).ToArray())
                StrategyComboBox.Items.Add(g);
            //StrategyComboBox.Items.Add("ALL"); <------------------- TO DO

            LoadTheBackOffice();

            BackOfficeTimer.Tick += BackOfficeTimerTick;
            BackOfficeTimer.Start();
        }

        private void LoadTheBackOffice()
        {
            var dbs = db.DBStrategies.Execute(MergeOption.AppendOnly);

            foreach (var dbStrategiese in dbs)
            {
                dbStrategiese.DBInstruments.Load();
                StrategyDetails[dbStrategiese.ID] = dbStrategiese.ID + ":  " + dbStrategiese.Name + " - " + dbStrategiese.Info + " - " + dbStrategiese.Pattern + " - " + dbStrategiese.CreationDate;
                Instruments[dbStrategiese.ID] = new List<Instrument>();
                InventoryOrders[dbStrategiese.ID] = new List<Order>();
                TradedOrders[dbStrategiese.ID] = new List<Order>();
                foreach (var dbi in dbStrategiese.DBInstruments)
                {
                    var i = new Instrument(dbi.ID, DataService, OrderService);
                    Instruments[dbStrategiese.ID].Add(i);
                    i.Suscribe();
                    var inv = new Inventories(i);
                    inv.Inventory(SelectedDate + dbStrategiese.BuildAt, dbStrategiese.ID);
                    inv.Traded(SelectedDate + dbStrategiese.BuildAt, dbStrategiese.ID);
                    InventoryOrders[dbStrategiese.ID].AddRange(inv.InventoryOrders.Values.ToList());
                    TradedOrders[dbStrategiese.ID].AddRange(inv.TradedOrders.Values.ToList());
                }
            }
        }

        private void BackOfficeTimerTick(object sender, EventArgs e)
        {
            var tradedpl = 0m; var tradedtc = 0.0;
            foreach (DataGridViewRow dgvr in TradedDataGridView.Rows)
            {
                tradedpl += (decimal)dgvr.Cells["PL"].Value;
                tradedtc += (double)dgvr.Cells["Fees"].Value;
            }
            TCtoolStripLabel.Text = tradedtc.ToString("N1");
            NETPLtoolStripLabel.Text = tradedpl.ToString("N1");

            var invpl = 0m; var invtc = 0.0;
            foreach (DataGridViewRow dgvr in InventoryDataGridView.Rows)
            {
                invpl += (decimal)dgvr.Cells["PL"].Value;
                invtc += (double)dgvr.Cells["Fees"].Value;
            }
            InventoryNETPLtoolStripLabel.Text = invpl.ToString("N1");
            InventoryTCtoolStripLabel.Text = invtc.ToString("N1");
        }
        private void DateTimePickerHostValidated(object sender, EventArgs e)
        {
            SelectedDate = DateTime.Parse(dateTimePickerHost.Text);
            StrategyComboBox_DropDownClosed(this, new EventArgs());
        }
        private void StrategyComboBox_DropDownClosed(object sender, EventArgs e)
        {
            if (OrderService == null)
                return;

            if (OrderService.isConnected)
            {
                if (StrategyComboBox.SelectedItem != null)
                {
                    if (StrategyComboBox.SelectedItem is Guid)
                    {
                        var StratId = (Guid)StrategyComboBox.SelectedItem;

                        if (ParentForm != null)
                            ParentForm.Name = StrategyDetails[StratId];

                        InventoryDataGridView.DataSource = ToInventoryBackOfficeInstruments(Instruments[StratId]);
                        TradedDataGridView.DataSource = ToTradedBackOfficeInstruments(Instruments[StratId]);
                        InventoryOrderDataGridView.DataSource = ToBackOfficeOrders(InventoryOrders[StratId]);
                        TradedOrderDataGridView.DataSource = ToBackOfficeOrders(TradedOrders[StratId]);
                    }
                    else if (StrategyComboBox.SelectedItem is String)
                    {
                        if (ParentForm != null)
                            ParentForm.Name = "ALL Strategies";

                        // TO DO
                    }
                }
            }
        }
        private void InventoryDataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            var instrumentId = ((InventoryBackOfficeInstrument)(((DataGridView)sender).Rows[e.RowIndex]).DataBoundItem).Id;

            foreach (DataGridViewRow dvr in InventoryOrderDataGridView.Rows)
            {
                var o = (BackOfficeOrder)dvr.DataBoundItem;
                if (o.InstrummentId != instrumentId)
                    dvr.Visible = false;
                else
                    dvr.Visible = true;
            }

            OstDataGridView.DataSource = db.DBOst.Where(u => u.DBInstruments.ID == instrumentId).ToArray();
        }
        private void TradedDataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            var instrumentId = ((TradedBackOfficeInstrument)(((DataGridView)sender).Rows[e.RowIndex]).DataBoundItem).Id;

            foreach (DataGridViewRow dvr in TradedOrderDataGridView.Rows)
            {
                var o = (BackOfficeOrder)dvr.DataBoundItem;
                if (o.InstrummentId != instrumentId)
                    dvr.Visible = false;
                else
                    dvr.Visible = true;
            }
        }
        private void OrdersReportToolStripButton_Click(object sender, EventArgs e)
        {
            new OrdersReportForm().Show();
            new ExecutionsReportForm().Show();
        }

        private static BackOfficeOrder[] ToBackOfficeOrders(IEnumerable<Order> list)
        {
            var boo = new List<BackOfficeOrder>();
            foreach (var o in list)
                boo.Add(new BackOfficeOrder(o));
            return boo.ToArray();
        }
        private static InventoryBackOfficeInstrument[] ToInventoryBackOfficeInstruments(IEnumerable<Instrument> list)
        {
            var boo = new List<InventoryBackOfficeInstrument>();
            foreach (var i in list)
                boo.Add(new InventoryBackOfficeInstrument(i));
            return boo.ToArray();
        }
        private static TradedBackOfficeInstrument[] ToTradedBackOfficeInstruments(IEnumerable<Instrument> list)
        {
            var boo = new List<TradedBackOfficeInstrument>();
            foreach (var i in list)
                boo.Add(new TradedBackOfficeInstrument(i));
            return boo.ToArray();
        }
        internal class BackOfficeOrder
        {
            public Guid OrderId { get; private set; }
            public Guid InstrummentId { get; private set; }
            public DateTime Created { get; private set; }
            public OrderStyle Style { get; private set; }
            public OrderSide Side { get; private set; }
            public int TargetQty { get; private set; }
            public decimal TargetPrice { get; private set; }
            public decimal AvgPrice{ get; private set; }
            public int TotalQty { get; private set; }
            public Guid StratId { get; private set; }
            
            public BackOfficeOrder(Order o)
            {
                OrderId = o.Id;
                InstrummentId = o.InstrumentId;
                Created = o.SendTime;
                Style = o.Style;
                Side = o.Side;
                TargetQty = o.TargetQuantity;
                TargetPrice = o.TargetPrice;
                AvgPrice = o.ExecutedAveragePrice;
                TotalQty = o.TotalExecutedQuantity;
                StratId = o.StrategyId;
            }
        }
        internal class TradedBackOfficeInstrument
        {
            public Guid Id { get; private set; }
            public String Name { get; private set; }
            public int Inventory { get; private set; }
            public decimal AvgPrice { get; private set; }
            public decimal LastPrice { get; private set; }
            public String Curncy { get; private set; }
            public double Reference { get; private set; }
            public decimal Realized { get; private set; }
            public decimal UnRealized { get; private set; }
            public decimal PL { get; private set; }
            public double Fees { get; private set; }


            public TradedBackOfficeInstrument(Instrument instrument)
            {
                Id = instrument.Id;
                Name = instrument.StaticData.Name;
                Inventory = instrument[Expo.Traded].Balance;
                var s = instrument.StaticData.Rules.Tick.ToString("E");
                AvgPrice = Math.Round(instrument[Expo.Traded].BalancePrice, (int)char.GetNumericValue(s.Last()));
                Curncy = instrument.StaticData.Currency.Ticker;
                Reference = instrument.StaticData.Currency.ReferencePrice;
                Realized = Math.Round(instrument[Expo.Traded].Realized, 2);
                UnRealized = Math.Round(instrument[Expo.Traded].UnRealized, 2);
                PL = Math.Round(instrument[Expo.Traded].PL, 2);
                Fees = Math.Round(instrument.StaticData.Fees.Tc,2);
                LastPrice = instrument.Blotter[QuoteLevel.One].Mid;
            }
        }
        internal class InventoryBackOfficeInstrument
        {
            public Guid Id { get; private set; }
            public String Name { get; private set; }
            public int Inventory { get; private set; }
            public decimal AvgPrice { get; private set; }
            public decimal LastPrice { get; private set; }
            public String Curncy { get; private set; }
            public double Reference { get; private set; }
            public decimal Realized { get; private set; }
            public decimal UnRealized { get; private set; }
            public decimal PL { get; private set; }
            public double Fees { get; private set; }


            public InventoryBackOfficeInstrument(Instrument instrument)
            {
                Id = instrument.Id;
                Name = instrument.StaticData.Name;
                Inventory = instrument[Expo.Inventory].Balance;
                var s = instrument.StaticData.Rules.Tick.ToString("E");
                AvgPrice = Math.Round(instrument[Expo.Inventory].BalancePrice, (int)char.GetNumericValue(s.Last()));
                Curncy = instrument.StaticData.Currency.Ticker;
                Reference = instrument.StaticData.Currency.ReferencePrice;
                Realized = Math.Round(instrument[Expo.Inventory].Realized, 2);
                UnRealized = Math.Round(instrument[Expo.Inventory].UnRealized, 2);
                PL = Math.Round(instrument[Expo.Inventory].PL, 2);
                Fees = Math.Round(instrument.StaticData.Fees.TcInventory,2);
                LastPrice = instrument.Blotter[QuoteLevel.One].Mid;
            }
        }

        protected override void OnHandleDestroyed(EventArgs e)
        {
            BackOfficeTimer.Stop();
            base.OnHandleDestroyed(e);
        }
    }
}
